package com.iwhalecloud.bss.kite.cucc.manager.scene.service.operate;

import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.validate.annotation.KiteNotNull;
import com.iwhalecloud.bss.kite.cucc.manager.inst.CuccKiteOfferInstAcct;
import com.iwhalecloud.bss.kite.dataservice.util.IdUtils;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.*;
import com.iwhalecloud.bss.kite.manager.inst.graph.IInstRelGraph;
import com.iwhalecloud.bss.kite.manager.inst.graph.impl.InstVertex;
import com.iwhalecloud.bss.kite.manager.scene.service.operate.OperateChangeService;
import com.iwhalecloud.bss.kite.manager.scene.service.operate.OperateInstService;
import com.iwhalecloud.bss.kite.manager.scene.util.InstRelGraphUtils;
import com.iwhalecloud.bss.kite.manager.scene.util.InstUtils;
import com.iwhalecloud.bss.kite.manager.scene.util.SceneInstUtils;
import com.iwhalecloud.bss.kite.manager.scene.vertex.ISubOfferInstAcct;
import com.iwhalecloud.bss.kite.manager.scene.vertex.ISubProdInstAcct;
import com.iwhalecloud.bss.kite.manager.transaction.TransactionContext;
import com.iwhalecloud.bss.kite.manager.util.InstTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 账户实例处理类
 */
@Service("manager.localOperOfferInstAcctRelService")
public class LocalOperateOfferInstAcctRelService extends OperateInstService {

	@Autowired
	private IOperateSceneInstService operateSceneInstService;

	@Autowired
	private IQuerySceneInstService querySceneInstService;

	/**
     * 根据offerId查询账户实例
     * @param sceneInstId
     * @param acctId
     * @param acctDesc
     * @param acctItemGroupId
     * @return
     */
    public List<KiteOfferInstAcct> listOfferInstAcctRels(String sceneInstId, String offerInstId) {
    	List<KiteOfferInstAcct> allAcctRels = querySceneInstService.getExtParameterValue(sceneInstId, "offerInstAcctRels");
    	if (allAcctRels == null) {
    		allAcctRels = new ArrayList<>();
    		return allAcctRels;
    	}
    	if (!KiteStringUtils.isEmpty(offerInstId)) {
    		allAcctRels = allAcctRels.stream().filter((acct) -> acct.getOfferInstId().equals(offerInstId)).collect(Collectors.toList());
    	}
    	return allAcctRels;
    }


    public List<KiteOfferInstAcct> listOfferInstAcctRels(String sceneInstId) {
        List<KiteOfferInstAcct> allAcctRels = querySceneInstService.getExtParameterValue(sceneInstId, "offerInstAcctRels");
        if (allAcctRels == null) {
            allAcctRels = new ArrayList<>();
            return allAcctRels;
        }
        return allAcctRels;
    }

	/**
     * 添加账户实例
     * @param sceneInstId
     * @param acctId
     * @param acctDesc
     * @param acctItemGroupId
     * @return
     */
    public String addOfferInstAcctRels(String custId, String sceneInstId, List<KiteOfferInstAcct> newAcctRels) {
        //KiteSceneInst sceneInst = TransactionContext.getContainer().getSceneInst(sceneInstId);
        //IInstRelGraph sceneInstRelGraph = SceneInstUtils.getSceneInstRelGraph(sceneInst);
        String result = null;
        List<KiteOfferInstAcct> allAcctRels = querySceneInstService.getExtParameterValue(sceneInstId, "offerInstAcctRels");
        if (KiteListUtils.isEmpty(allAcctRels)) {
            allAcctRels = new ArrayList<>();
        }

        // 业务变更新增判断逻辑
        boolean flag = true;
        if (KiteListUtils.isNotEmpty(newAcctRels)) {
            KiteOfferInstAcct kiteOfferInstAcct = newAcctRels.get(0);
            String acctId = allAcctRels.stream()
                .filter(allAcctRel -> KiteStringUtils.equals(allAcctRel.getAcctId(), kiteOfferInstAcct.getAcctId()))
                .findFirst().map(KiteOfferInstAcct::getAcctId).orElse("");
            if (KiteStringUtils.isNotEmpty(acctId)) {
                flag = false;
            }
        }
        //判断选择的账户中是否有默认的账户
        List<KiteOfferInstAcct> defaultNewAcctRels = newAcctRels.stream().filter(KiteOfferInstAcct -> {
            return "1".equals(KiteOfferInstAcct.getIsDefault());
        }).collect(Collectors.toList());
        //第一次选择多个默认的付费关系
        if (defaultNewAcctRels.size() > 1) {
            return "勾选商品不可添加多个默认付费关系";
        }
        if (KiteListUtils.isNotEmpty(newAcctRels) && flag) {
            String payCycle = newAcctRels.get(0).getFeeCycle();
            String accountCycle = newAcctRels.get(0).getAccountCycle();
            boolean isSamechangeCycle = newAcctRels.stream().anyMatch(KiteOfferInstAcct -> {
               return !KiteOfferInstAcct.getFeeCycle().equals(payCycle) || !KiteOfferInstAcct.getAccountCycle().equals(accountCycle);
            });
            if (isSamechangeCycle) {
                return "商品的所选账户信息中的账务周期，缴费周期必须保持一致";
            }
        }
        if (KiteListUtils.isNotEmpty(defaultNewAcctRels) && KiteListUtils.isNotEmpty(allAcctRels) && flag) {
            boolean isDefaultInAlreadyAcct = false;
            KiteOfferInstAcct alreadyOfferInstAcctRel = allAcctRels.stream().filter(KiteOfferInstAcct -> {
                return "1".equals(KiteOfferInstAcct.getIsDefault());
            }).findFirst().orElse(null);
            if (!KiteObjectUtils.isEmpty(alreadyOfferInstAcctRel)) {
                isDefaultInAlreadyAcct = defaultNewAcctRels.stream().anyMatch(KiteOfferInstAcct -> {
                    return !alreadyOfferInstAcctRel.getInstId().equals(KiteOfferInstAcct.getInstId());
                });
            }
            if (isDefaultInAlreadyAcct) {
                result = "勾选商品中已存在默认付费关系，不可添加多个默认付费关系";
                return result;
            }
        }

        //判断已有的付费关系和在选的账户的两个周期要一致
        if (KiteListUtils.isNotEmpty(allAcctRels) && flag) {
            KiteOfferInstAcct KiteOfferInstAcct = allAcctRels.get(0);
            //账务周期
            String accountCycle = KiteOfferInstAcct.getAccountCycle();
            //缴费周期
            String payCycle = KiteOfferInstAcct.getFeeCycle();
            //如果两个周期有一个与保存了的付费关系不相等
            boolean isSameCycle = newAcctRels.stream().anyMatch(KiteOfferInstAcct1 -> {
                return (!KiteOfferInstAcct1.getAccountCycle().equals(accountCycle) || !KiteOfferInstAcct1.getFeeCycle().equals(payCycle))
                    && !KiteOfferInstAcct.getInstId().equals(KiteOfferInstAcct1.getInstId());
            });
            if (isSameCycle) {
                result = "商品的所选账户信息中的账务周期，缴费周期必须保持一致";
                return result;
            }
        }

    	List<KiteOfferInstAcct> addAcctRels = newAcctRels.stream().filter((acct) -> KiteStringUtils.isEmpty(acct.getInstId())).collect(Collectors.toList());
    	List<KiteOfferInstAcct> updateAcctRels = newAcctRels.stream().filter((acct) -> !KiteStringUtils.isEmpty(acct.getInstId())).collect(Collectors.toList());

    	//更新
    	for (KiteOfferInstAcct updateAcctRel : updateAcctRels) {
    		for (KiteOfferInstAcct acct : allAcctRels) {
    			if (acct.getInstId().equals(updateAcctRel.getInstId())) {
    				KiteBeanUtils.copyProperties(updateAcctRel, acct);
    				acct.setInstType(InstType.OFFER_INST_ACCT);
    	            acct.setActionType(ActionType.A);
    	            acct.setOfferName(querySceneInstService.getOfferInst(custId, acct.getOfferInstId()).getOfferName());
        		}
        	}
    	}
    	//新增
    	for (KiteOfferInstAcct addAcctRel : addAcctRels) {
    		addAcctRel.setInstId(IdUtils.generateInstId(InstType.PROD_INST_ACCT));
    		addAcctRel.setInstType(InstType.OFFER_INST_ACCT);
    		addAcctRel.setActionType(ActionType.A);
    		addAcctRel.setOfferName(querySceneInstService.getOfferInst(custId, addAcctRel.getOfferInstId()).getOfferName());
    		allAcctRels.add(addAcctRel);
    	}

    	operateSceneInstService.putExtParameter(sceneInstId, "offerInstAcctRels", allAcctRels);

    	return result;
    }

    /**
     * 添加账户实例
     * @param sceneInstId
     * @param acctId
     * @param acctDesc
     * @param acctItemGroupId
     * @return
     */
    public List<KiteOfferInstAcct> addOfferInstAcctRel(String sceneInstId, String offerInstId, String acctId, String acctName, String acctType, String acctItemId,
    											String isDefault, String accountCycle, String feeCycle, String payWay, String payLimit, String startDate, String endDate) {

        KiteOfferInstAcct offerInstAcctRel = new KiteOfferInstAcct();
        offerInstAcctRel.setInstId(IdUtils.generateInstId(InstType.PROD_INST_ACCT));
        offerInstAcctRel.setAcctId(acctId);
        offerInstAcctRel.setAcctName(acctName);
        offerInstAcctRel.setAcctType(acctType);
        offerInstAcctRel.setAcctItemId(acctItemId);
        offerInstAcctRel.setIsDefault(isDefault);
        offerInstAcctRel.setAccountCycle(accountCycle);
        offerInstAcctRel.setFeeCycle(feeCycle);
        offerInstAcctRel.setPayWay(payWay);
        offerInstAcctRel.setPayLimit(payLimit);
        offerInstAcctRel.setStartDate(startDate);
        offerInstAcctRel.setEndDate(endDate);
        offerInstAcctRel.setInstType(InstType.OFFER_INST_ACCT);
        offerInstAcctRel.setActionType(ActionType.A);

        //先保存到扩展信息里面
        String key = "offerInstAcctRels";
        List<KiteOfferInstAcct> acctRels = querySceneInstService.getExtParameterValue(sceneInstId, key);
        if (acctRels == null) {
        	acctRels = new ArrayList<>();
        }
        acctRels.add(offerInstAcctRel);
        operateSceneInstService.putExtParameter(sceneInstId, key, acctRels);
        return acctRels;
    }

    /**
     * 把账户实例添加到接入产品实例中
     * @param sceneInstId
     * @param prodInstAcct
     * @param prodInstId
     * @param relType
     * @param relActionType
     * @return
     */
    @Validated
    public String addOfferInstAcctRel(String sceneInstId, @KiteNotNull KiteOfferInstAcct offerInstAcctRel, String offerInstId, InstType instType,
        @KiteNotNull RelType relType, ActionType relActionType) {
        KiteSceneInst sceneInst = TransactionContext.getContainer().getSceneInst(sceneInstId);
        String custId = SceneInstUtils.getCustId(sceneInst);
        InstVertex instVertex = InstRelGraphUtils.getCustInstVertex(custId, instType, offerInstId);
        if (Objects.isNull(instVertex)) {
            ErrorConsts.OFFER_INST_NOT_EXIST.throwOut(offerInstId, custId);
        }

        return addSubInst(sceneInst, instType, offerInstId, offerInstAcctRel, relType, relActionType);
    }

    /**
     * 把账户实例添加到接入产品实例中(覆盖已有的账户)
     * @param sceneInstId
     * @param acctId
     * @param acctDesc
     * @param acctItemGroupId
     * @param prodInstId
     * @param relType
     * @param relActionType
     * @return
     */
    public KiteOfferInstAcct setOfferInstAcctRel(String sceneInstId, String acctId, String acctName, String acctItemId,
        String offerInstId, InstType offerInstType, RelType relType, ActionType relActionType) {
        KiteSceneInst sceneInst = TransactionContext.getContainer().getSceneInst(sceneInstId);
        String custId = SceneInstUtils.getCustId(sceneInst);
        InstVertex instVertex = InstRelGraphUtils.getCustInstVertex(custId, offerInstType, offerInstId);
        if (Objects.isNull(instVertex)) {
            ErrorConsts.OFFER_INST_NOT_EXIST.throwOut(offerInstId, custId);
        }

        KiteOfferInstAcct offerInstAcctRel = new KiteOfferInstAcct();
        offerInstAcctRel.setInstId(IdUtils.generateInstId(InstType.PROD_INST_ACCT));
        offerInstAcctRel.setAcctId(acctId);
        offerInstAcctRel.setAcctDesc(acctName);
        offerInstAcctRel.setAcctItemId(acctItemId);
        offerInstAcctRel.setInstType(InstType.OFFER_INST_ACCT);
        offerInstAcctRel.setActionType(ActionType.A);
        return setAcctInst(sceneInstId, offerInstAcctRel, offerInstType, offerInstId, relType, relActionType, "", "");
    }

    /**
     * 删除账户实例
     * @param sceneInstId
     * @param prodInstAcctRelId
     * @return
     */
    public Boolean deleteOfferInstAcctRel(String sceneInstId, String offerInstId, String offerInstAcctRelId, InstType offerInstType) {
        /*KiteSceneInst sceneInst = TransactionContext.getContainer().getSceneInst(sceneInstId);
        String custId = SceneInstUtils.getCustId(sceneInst);
        IInstRelGraph custInstRelGraph = TransactionContext.getContainer().getCustInstRelGraph(custId);
        InstVertex instVertex = InstRelGraphUtils.getCustInstVertex(custId, InstType.OFFER_INST_ACCT_REL, offerInstAcctRelId);
        if (Objects.isNull(instVertex)) {
            ErrorConsts.OFFER_INST_NOT_EXIST.throwOut(offerInstAcctRelId, custId);
        }

        if (instVertex instanceof IParentProdInst) {
            ((IParentProdInst) instVertex).listParentProdInsts(custInstRelGraph);
        }

        InstType parentInstType = null;
        String parentInstId = "";
        List<InstVertex> prodInstVertexs = InstRelGraphUtils.listParentInstVertexs(custInstRelGraph, instVertex,
            RelType.OFFER_ACCT_REL_TYPE_1000, offerInstType);
        InstVertex prodInstVertex = InstRelGraphUtils.getInstVertex(prodInstVertexs);
        if (Objects.nonNull(prodInstVertex)) {
            parentInstType = prodInstVertex.getInstType();
            parentInstId = prodInstVertex.getInstId();
        }
        return deleteSubInst(sceneInst, parentInstType, parentInstId, InstType.OFFER_INST_ACCT_REL, offerInstAcctRelId);*/
    	String key = "offerInstAcctRels";

    	List<KiteOfferInstAcct> acctRels = querySceneInstService.getExtParameterValue(sceneInstId, key);
        if (acctRels == null) {
        	return Boolean.TRUE;
        }
        Iterator<KiteOfferInstAcct> it = acctRels.iterator();
        while (it.hasNext()) {
        	KiteOfferInstAcct acct = it.next();
        	if (offerInstAcctRelId.equals(acct.getInstId())) {
        		it.remove();
        		break;
        	}
        }
    	operateSceneInstService.putExtParameter(sceneInstId, key, acctRels);

    	return Boolean.TRUE;

    }

    /**
     * 把账户实例添加到接入产品/销售品实例中(覆盖已有的账户)
     * @param sceneInstId
     * @param prodInstAcct
     * @param parentInstType
     * @param parentInstId
     * @param relType
     * @param relActionType
     * @param roleId
     * @param detailId
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T extends KiteInst> T setAcctInst(String sceneInstId, KiteOfferInstAcct acctInst, InstType parentInstType,
        String parentInstId, RelType relType, ActionType relActionType, String roleId, String detailId) {
        if (Objects.isNull(acctInst)) {
            return null;
        }

        KiteSceneInst sceneInst = TransactionContext.getContainer().getSceneInst(sceneInstId);
        String custId = SceneInstUtils.getCustId(sceneInst);
        IInstRelGraph custInstRelGraph = TransactionContext.getContainer().getCustInstRelGraph(custId);
        InstVertex instVertex = InstRelGraphUtils.getCustInstVertex(custId, parentInstType, parentInstId);
        if (Objects.isNull(instVertex)) {
            if (Objects.equals(InstType.PROD_INST, parentInstType)) {
                ErrorConsts.PROD_INST_NOT_EXIST.throwOut(parentInstId, custId);
            }
            else if (InstTypeUtils.isOfferInst(parentInstType)) {
                ErrorConsts.OFFER_INST_NOT_EXIST.throwOut(parentInstId, custId);
            }
            else {
                ErrorConsts.INST_NOT_EXIST.throwOut(parentInstType, parentInstId, custId);
            }
        }

        if (instVertex instanceof ISubProdInstAcct) {
            ((ISubProdInstAcct) instVertex).listSubProdInstAccts(custInstRelGraph);
        }
        if (instVertex instanceof ISubOfferInstAcct) {
            ((ISubOfferInstAcct) instVertex).listSubOfferInstAccts(custInstRelGraph);
        }

        List<InstVertex> acctInstVertexs = InstRelGraphUtils.listSubInstVertexs(custInstRelGraph, instVertex, relType,
            acctInst.getInstType());
        List<IKiteInst> insts = new ArrayList<>();
        List<KiteAcctInst> deleteAcctInsts = new ArrayList<>();
        // 是否已经存在相同acctId的账户实例
        KiteAcctInst existsAcctInst = null;
        List<KiteAcctInst> acctInsts = InstUtils.transformInsts(SceneInstUtils.getCustId(sceneInst),
            acctInstVertexs);
        for (KiteAcctInst kiteAcctInst : acctInsts) {
            if (Objects.nonNull(existsAcctInst)) {
                deleteAcctInsts.add(kiteAcctInst);
                continue;
            }

            if (Objects.equals(acctInst.getAcctId(), kiteAcctInst.getAcctId())) {
                if (!Objects.equals(ActionType.D, kiteAcctInst.getActionType())
                    && !Objects.equals(ActionType.X, kiteAcctInst.getActionType())) {
                    existsAcctInst = kiteAcctInst;
                    // 不重复添加
                    continue;
                }
                else if (Objects.nonNull(OperateChangeService.getDeleteInstChange(sceneInstId,
                    kiteAcctInst.getInstType(), kiteAcctInst.getInstId()))) {
                    existsAcctInst = kiteAcctInst;
                    // 如果已经存在并且是当前场景实例删除的，恢复actionType，D -> M/K，X -> A
                    recoverSubInstActionType(sceneInst, kiteAcctInst, instVertex.getInstType(), instVertex.getInstId(),
                        relType);
                    insts.add(kiteAcctInst);
                }
            }
            else {
                deleteAcctInsts.add(kiteAcctInst);
            }
        }

        for (KiteAcctInst deleteAcctInst : deleteAcctInsts) {
            deleteSubInst(sceneInst, parentInstType, parentInstId, deleteAcctInst);
        }

        if (Objects.nonNull(existsAcctInst)) {
            insts.add(sceneInst);
            TransactionContext.getContainer().putInsts(insts);
            return (T) existsAcctInst;
        }

        addSubInst(sceneInst, parentInstType, parentInstId, acctInst, relType, relActionType, roleId, detailId);
        return (T) acctInst;
    }


    /**
     * 产品包-获取销售品实例的所有账户级销售品实例
     * @param custId
     * @param offerInstId
     *
     * @return
     */
    public List<CuccKiteOfferInstAcct> listOfferInstAccts(String custId, String offerInstId) {
        IInstRelGraph custInstRelGraph = TransactionContext.getContainer().getCustInstRelGraph(custId);
        InstVertex instVertex = InstRelGraphUtils.getCustOfferInstVertex(custId, offerInstId);
        if (Objects.isNull(instVertex)) {
            ErrorConsts.OFFER_INST_NOT_EXIST.throwOut(offerInstId, custId);
        }

        if (instVertex instanceof ISubOfferInstAcct) {
            ((ISubOfferInstAcct) instVertex).listSubOfferInstAccts(custInstRelGraph);
        }

        List<InstVertex> instVertexs = InstRelGraphUtils.listSubInstVertexs(custInstRelGraph, instVertex,
            RelType.OFFER_OBJ_REL_TYPE_170000, InstType.OFFER_INST_ACCT);
        return InstUtils.transformInsts(custId, instVertexs);
    }


    /**
     * 校验添加的账户
     * 原默认账户变成非默认账户，开始账期不能是当月以及当月之前
     * @param offerInstAcct
     * @param delOfferInstAccts
     * @return
     */
    public String checkAddingOfferInstAcct(CuccKiteOfferInstAcct offerInstAcct, List<KiteOfferInstAcct> delOfferInstAccts) {
        String result = null;

        for (KiteOfferInstAcct kiteOfferInstAcct : delOfferInstAccts) {
            String delAcctId = kiteOfferInstAcct.getAcctId();
            String delIsDefault = kiteOfferInstAcct.getIsDefault();
            String delStartDate = kiteOfferInstAcct.getStartDate();

            if (KiteStringUtils.equals("1", delIsDefault)) {
                String newIsDefault = offerInstAcct.getIsDefault();
                String newAcctId = offerInstAcct.getAcctId();
                String newStartDate = offerInstAcct.getStartDate();
                if (!KiteStringUtils.equals("1", newIsDefault) && !KiteStringUtils.equals(offerInstAcct.getActionType().name(), ActionType.D.name())
                    && KiteStringUtils.equals(newAcctId, delAcctId)
                    && KiteStringUtils.equals(newStartDate, delStartDate)) {
                    return result = "原默认账户变成非默认账户，开始账期不能是当月以及当月之前";
                }
            }
        }

        return result;
    }

}
